home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / gettext / intl / plural.y < prev    next >
Encoding:
Lex Description  |  2007-03-05  |  7.3 KB  |  384 lines

  1. %{
  2. /* Expression parsing for plural form selection.
  3.    Copyright (C) 2000-2001, 2003, 2005 Free Software Foundation, Inc.
  4.    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
  5.  
  6.    This program is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU Library General Public License as published
  8.    by the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    Library General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU Library General Public
  17.    License along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  19.    USA.  */
  20.  
  21. /* For bison < 2.0, the bison generated parser uses alloca.  AIX 3 forces us
  22.    to put this declaration at the beginning of the file.  The declaration in
  23.    bison's skeleton file comes too late.  This must come before <config.h>
  24.    because <config.h> may include arbitrary system headers.
  25.    This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0.  */
  26. #if defined _AIX && !defined __GNUC__
  27.  #pragma alloca
  28. #endif
  29.  
  30. #ifdef HAVE_CONFIG_H
  31. # include <config.h>
  32. #endif
  33.  
  34. #include <stddef.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include "plural-exp.h"
  38.  
  39. /* The main function generated by the parser is called __gettextparse,
  40.    but we want it to be called PLURAL_PARSE.  */
  41. #ifndef _LIBC
  42. # define __gettextparse PLURAL_PARSE
  43. #endif
  44.  
  45. #define YYLEX_PARAM    &((struct parse_args *) arg)->cp
  46. #define YYPARSE_PARAM    arg
  47. %}
  48. %pure_parser
  49. %expect 7
  50.  
  51. %union {
  52.   unsigned long int num;
  53.   enum operator op;
  54.   struct expression *exp;
  55. }
  56.  
  57. %{
  58. /* Prototypes for local functions.  */
  59. static int yylex (YYSTYPE *lval, const char **pexp);
  60. static void yyerror (const char *str);
  61.  
  62. /* Allocation of expressions.  */
  63.  
  64. static struct expression *
  65. new_exp (int nargs, enum operator op, struct expression * const *args)
  66. {
  67.   int i;
  68.   struct expression *newp;
  69.  
  70.   /* If any of the argument could not be malloc'ed, just return NULL.  */
  71.   for (i = nargs - 1; i >= 0; i--)
  72.     if (args[i] == NULL)
  73.       goto fail;
  74.  
  75.   /* Allocate a new expression.  */
  76.   newp = (struct expression *) malloc (sizeof (*newp));
  77.   if (newp != NULL)
  78.     {
  79.       newp->nargs = nargs;
  80.       newp->operation = op;
  81.       for (i = nargs - 1; i >= 0; i--)
  82.     newp->val.args[i] = args[i];
  83.       return newp;
  84.     }
  85.  
  86.  fail:
  87.   for (i = nargs - 1; i >= 0; i--)
  88.     FREE_EXPRESSION (args[i]);
  89.  
  90.   return NULL;
  91. }
  92.  
  93. static inline struct expression *
  94. new_exp_0 (enum operator op)
  95. {
  96.   return new_exp (0, op, NULL);
  97. }
  98.  
  99. static inline struct expression *
  100. new_exp_1 (enum operator op, struct expression *right)
  101. {
  102.   struct expression *args[1];
  103.  
  104.   args[0] = right;
  105.   return new_exp (1, op, args);
  106. }
  107.  
  108. static struct expression *
  109. new_exp_2 (enum operator op, struct expression *left, struct expression *right)
  110. {
  111.   struct expression *args[2];
  112.  
  113.   args[0] = left;
  114.   args[1] = right;
  115.   return new_exp (2, op, args);
  116. }
  117.  
  118. static inline struct expression *
  119. new_exp_3 (enum operator op, struct expression *bexp,
  120.        struct expression *tbranch, struct expression *fbranch)
  121. {
  122.   struct expression *args[3];
  123.  
  124.   args[0] = bexp;
  125.   args[1] = tbranch;
  126.   args[2] = fbranch;
  127.   return new_exp (3, op, args);
  128. }
  129.  
  130. %}
  131.  
  132. /* This declares that all operators have the same associativity and the
  133.    precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
  134.    There is no unary minus and no bitwise operators.
  135.    Operators with the same syntactic behaviour have been merged into a single
  136.    token, to save space in the array generated by bison.  */
  137. %right '?'        /*   ?        */
  138. %left '|'        /*   ||        */
  139. %left '&'        /*   &&        */
  140. %left EQUOP2        /*   == !=    */
  141. %left CMPOP2        /*   < > <= >=    */
  142. %left ADDOP2        /*   + -    */
  143. %left MULOP2        /*   * / %    */
  144. %right '!'        /*   !        */
  145.  
  146. %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
  147. %token <num> NUMBER
  148. %type <exp> exp
  149.  
  150. %%
  151.  
  152. start:      exp
  153.       {
  154.         if ($1 == NULL)
  155.           YYABORT;
  156.         ((struct parse_args *) arg)->res = $1;
  157.       }
  158.     ;
  159.  
  160. exp:      exp '?' exp ':' exp
  161.       {
  162.         $$ = new_exp_3 (qmop, $1, $3, $5);
  163.       }
  164.     | exp '|' exp
  165.       {
  166.         $$ = new_exp_2 (lor, $1, $3);
  167.       }
  168.     | exp '&' exp
  169.       {
  170.         $$ = new_exp_2 (land, $1, $3);
  171.       }
  172.     | exp EQUOP2 exp
  173.       {
  174.         $$ = new_exp_2 ($2, $1, $3);
  175.       }
  176.     | exp CMPOP2 exp
  177.       {
  178.         $$ = new_exp_2 ($2, $1, $3);
  179.       }
  180.     | exp ADDOP2 exp
  181.       {
  182.         $$ = new_exp_2 ($2, $1, $3);
  183.       }
  184.     | exp MULOP2 exp
  185.       {
  186.         $$ = new_exp_2 ($2, $1, $3);
  187.       }
  188.     | '!' exp
  189.       {
  190.         $$ = new_exp_1 (lnot, $2);
  191.       }
  192.     | 'n'
  193.       {
  194.         $$ = new_exp_0 (var);
  195.       }
  196.     | NUMBER
  197.       {
  198.         if (($$ = new_exp_0 (num)) != NULL)
  199.           $$->val.num = $1;
  200.       }
  201.     | '(' exp ')'
  202.       {
  203.         $$ = $2;
  204.       }
  205.     ;
  206.  
  207. %%
  208.  
  209. void
  210. internal_function
  211. FREE_EXPRESSION (struct expression *exp)
  212. {
  213.   if (exp == NULL)
  214.     return;
  215.  
  216.   /* Handle the recursive case.  */
  217.   switch (exp->nargs)
  218.     {
  219.     case 3:
  220.       FREE_EXPRESSION (exp->val.args[2]);
  221.       /* FALLTHROUGH */
  222.     case 2:
  223.       FREE_EXPRESSION (exp->val.args[1]);
  224.       /* FALLTHROUGH */
  225.     case 1:
  226.       FREE_EXPRESSION (exp->val.args[0]);
  227.       /* FALLTHROUGH */
  228.     default:
  229.       break;
  230.     }
  231.  
  232.   free (exp);
  233. }
  234.  
  235.  
  236. static int
  237. yylex (YYSTYPE *lval, const char **pexp)
  238. {
  239.   const char *exp = *pexp;
  240.   int result;
  241.  
  242.   while (1)
  243.     {
  244.       if (exp[0] == '\0')
  245.     {
  246.       *pexp = exp;
  247.       return YYEOF;
  248.     }
  249.  
  250.       if (exp[0] != ' ' && exp[0] != '\t')
  251.     break;
  252.  
  253.       ++exp;
  254.     }
  255.  
  256.   result = *exp++;
  257.   switch (result)
  258.     {
  259.     case '0': case '1': case '2': case '3': case '4':
  260.     case '5': case '6': case '7': case '8': case '9':
  261.       {
  262.     unsigned long int n = result - '0';
  263.     while (exp[0] >= '0' && exp[0] <= '9')
  264.       {
  265.         n *= 10;
  266.         n += exp[0] - '0';
  267.         ++exp;
  268.       }
  269.     lval->num = n;
  270.     result = NUMBER;
  271.       }
  272.       break;
  273.  
  274.     case '=':
  275.       if (exp[0] == '=')
  276.     {
  277.       ++exp;
  278.       lval->op = equal;
  279.       result = EQUOP2;
  280.     }
  281.       else
  282.     result = YYERRCODE;
  283.       break;
  284.  
  285.     case '!':
  286.       if (exp[0] == '=')
  287.     {
  288.       ++exp;
  289.       lval->op = not_equal;
  290.       result = EQUOP2;
  291.     }
  292.       break;
  293.  
  294.     case '&':
  295.     case '|':
  296.       if (exp[0] == result)
  297.     ++exp;
  298.       else
  299.     result = YYERRCODE;
  300.       break;
  301.  
  302.     case '<':
  303.       if (exp[0] == '=')
  304.     {
  305.       ++exp;
  306.       lval->op = less_or_equal;
  307.     }
  308.       else
  309.     lval->op = less_than;
  310.       result = CMPOP2;
  311.       break;
  312.  
  313.     case '>':
  314.       if (exp[0] == '=')
  315.     {
  316.       ++exp;
  317.       lval->op = greater_or_equal;
  318.     }
  319.       else
  320.     lval->op = greater_than;
  321.       result = CMPOP2;
  322.       break;
  323.  
  324.     case '*':
  325.       lval->op = mult;
  326.       result = MULOP2;
  327.       break;
  328.  
  329.     case '/':
  330.       lval->op = divide;
  331.       result = MULOP2;
  332.       break;
  333.  
  334.     case '%':
  335.       lval->op = module;
  336.       result = MULOP2;
  337.       break;
  338.  
  339.     case '+':
  340.       lval->op = plus;
  341.       result = ADDOP2;
  342.       break;
  343.  
  344.     case '-':
  345.       lval->op = minus;
  346.       result = ADDOP2;
  347.       break;
  348.  
  349.     case 'n':
  350.     case '?':
  351.     case ':':
  352.     case '(':
  353.     case ')':
  354.       /* Nothing, just return the character.  */
  355.       break;
  356.  
  357.     case ';':
  358.     case '\n':
  359.     case '\0':
  360.       /* Be safe and let the user call this function again.  */
  361.       --exp;
  362.       result = YYEOF;
  363.       break;
  364.  
  365.     default:
  366.       result = YYERRCODE;
  367. #if YYDEBUG != 0
  368.       --exp;
  369. #endif
  370.       break;
  371.     }
  372.  
  373.   *pexp = exp;
  374.  
  375.   return result;
  376. }
  377.  
  378.  
  379. static void
  380. yyerror (const char *str)
  381. {
  382.   /* Do nothing.  We don't print error messages here.  */
  383. }
  384.